package com.cyq.blog.util;


import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

/**
 * GenerateBeanUtil class
 *
 * @author chenyeqing
 * @date 2021/5/13
 */
public class GenerateBeanUtil {
    private static final String tableName = "blog";

    private static final String URL = "jdbc:mysql://localhost:3306/cyq_blog_db";
    private static final String NAME = "root";
    private static final String PASS = "123456";
    private static final String DRIVER = "com.mysql.cj.jdbc.Driver";

    private String[] fieldNames; // 实体类属性名的数组
    private String[] colNames;   // 列名数组
    private String[] colTypes;   // 列名类型数组
    private int[] colSizes;      // 列名大小数组

    private boolean fUtil = false; // 是否需要导入包java.util.*
    private boolean fSql = false;  // 是否需要导入包java.sql.*
    private boolean lombok = true;  // 是否需要导入包 lombok

    /**
     * 获取数据库连接
     */
    public static Connection getConnection() {
        Connection conn = null;

        try {
            Class.forName( DRIVER );
            conn = DriverManager.getConnection( URL, NAME, PASS );
        } catch ( Exception e1 ) {
            e1.printStackTrace();
        }

        return conn;
    }

    // 字符串格式转换      输入  = last_login_time   输出  = lastLoginTime
    public static String toNoBlank( String param ) {
        StringBuffer sbf = new StringBuffer();

        param = param.toLowerCase();

        if ( param.contains( "_" ) ) {
            String[] arr = param.split( "_" );

            for ( int i = 0; i < arr.length; i++ ) {
                if ( i == 0 ) {
                    sbf.append( arr[ i ] );

                    continue;
                }

                sbf.append( ( arr[ i ].charAt( 0 ) + "" ).toUpperCase()
                        + arr[ i ].substring( 1, arr[ i ].length() ) );
            }

            return sbf.toString();
        } else {
            return param;
        }
    }

    // 字符串格式转换      输入  = lastLoginTime    输出  = last_login_time
    public static String withBlank( String input2 ) {
        StringBuffer sbf = new StringBuffer();

        int tempPos = 0;

        for ( int i = 0; i < input2.length(); i++ ) {
            char a = input2.charAt( i );

            if ( ( int ) a >= ( int ) 'A' == true
                    && ( int ) a <= ( int ) 'Z' == true ) {
                sbf.append( input2.substring( tempPos, i ).toLowerCase() + "_" );

                tempPos = i;
            }
        }

        sbf.append( input2.substring( tempPos, input2.length() ).toLowerCase() );

        return sbf.toString();
    }

    // 生成数据库表对应的实体类
    public void genEntityTool() {
        Connection conn = getConnection();   // 得到数据库连接

        String strSql = "select * from " + tableName;

        try {
            PreparedStatement pstmt = conn.prepareStatement( strSql );
            ResultSetMetaData rsmd = pstmt.getMetaData();
            int size = rsmd.getColumnCount();    // 共有多少列

            fieldNames = new String[ size ];
            colNames = new String[ size ];
            colTypes = new String[ size ];
            colSizes = new int[ size ];

            for ( int i = 0; i < rsmd.getColumnCount(); i++ ) {
                colNames[ i ] = rsmd.getColumnName( i + 1 );
                colTypes[ i ] = rsmd.getColumnTypeName( i + 1 );

                fieldNames[ i ] = toNoBlank( rsmd.getColumnName( i + 1 ) );

                if ( colTypes[ i ].equalsIgnoreCase( "datetime" ) ) {
                    fUtil = true;
                }

                if ( colTypes[ i ].equalsIgnoreCase( "image" )
                        || colTypes[ i ].equalsIgnoreCase( "text" ) ) {
                    fSql = true;
                }

                colSizes[ i ] = rsmd.getColumnDisplaySize( i + 1 );
            }

            String content = parse( fieldNames, colTypes, colSizes );

            FileWriter fw = null;
            PrintWriter pw = null;

            try {
                // 创建输出文件夹和文件
                String fileName = "D:" + File.separator + "GitFile" + File.separator + "cyq-blog" + File.separator + "src"
                        + File.separator + "main" + File.separator + "java" + File.separator + "com" + File.separator + "cyq"
                        + File.separator + "blog" + File.separator + "entity" + File.separator
                        + initcap( toNoBlank( tableName ) ) + ".java";

                System.out.println( "fileName: " + fileName );

                File file = new File( fileName );

                File fileParent = file.getParentFile();    // 返回的是File类型，可以调用exsits()等方法
                String fileParentPath = file.getParent();  // 返回的是String类型

                System.out.println( "fileParentPath: " + fileParentPath );

                if ( !fileParent.exists() ) {
                    fileParent.mkdirs();   // 能创建多级目录
                }

                if ( !file.exists() ) {
                    file.createNewFile();  //有路径才能创建文件
                }

                fw = new FileWriter( fileName );

                pw = new PrintWriter( fw );

                pw.println( content );

                pw.flush();
            } catch ( IOException e ) {
                e.printStackTrace();
            } finally {
                try {
                    pw.close();
                } catch ( Exception e1 ) {
                    e1.printStackTrace();
                }

                try {
                    fw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        } catch ( SQLException e ) {
            e.printStackTrace();
        } finally {
            try {
                conn.close();
            } catch ( SQLException e ) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 解析处理(生成实体类主体代码)
     */
    private String parse( String[] fieldNames, String[] colTypes, int[] colSizes ) {
        StringBuffer sb = new StringBuffer();

        if ( fUtil ) {
            sb.append("import java.util.Date;  \r\n\r\n");
        }

        if ( fSql ) {
            sb.append("import java.sql.*;  \r\n\r\n");
        }
        if ( lombok ) {
            sb.append("import lombok.Data;  \r\n\r\n");
        }

        sb.append("import java.io.Serializable;  \r\n\r\n");

        sb.append( "@Data \r\n" );
        sb.append( "public class " + initcap( toNoBlank( tableName ) ) + " implements Serializable {  \r\n" );

        sb.append( "    private static final long serialVersionUID = 1L;  \r\n\r\n" );

        processAllAttrs( sb, fieldNames );

        sb.append( "\r\n" );

        sb.append( "}" );


        return sb.toString();
    }


    /**
     * 解析输出属性
     */
    private void processAllAttrs( StringBuffer sb, String[] fieldNames ) {
        for ( int i = 0; i < fieldNames.length; i++ ) {
            sb.append( "    private " + sqlType2JavaType( colTypes[ i ] ) + " " + fieldNames[ i ] + ";\r\n" );
        }
    }

    /**
     * 把输入字符串的首字母改成大写
     */
    private String initcap( String str ) {
        char[] ch = str.toCharArray();

        if ( ch[ 0 ] >= 'a' && ch[ 0 ] <= 'z' ) {
            ch[ 0 ] = ( char ) ( ch[ 0 ] - 32 );
        }

        return new String( ch );
    }

    //
    private String sqlType2JavaType( String sqlType ) {
        if ( sqlType.equalsIgnoreCase( "bit" ) ) {
            return "boolean";
        } else if (sqlType.equalsIgnoreCase("tinyint")) {
            return "byte";
        } else if (sqlType.equalsIgnoreCase("smallint")) {
            return "int";  //"short";
        } else if (sqlType.equalsIgnoreCase("int")) {
            return "int";
        } else if (sqlType.equalsIgnoreCase("bigint")) {
            return "long";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "double";  //"float";
        } else if (sqlType.equalsIgnoreCase("decimal")
                || sqlType.equalsIgnoreCase("numeric")
                || sqlType.equalsIgnoreCase("real")) {
            return "double";
        } else if (sqlType.equalsIgnoreCase("varchar")
                || sqlType.equalsIgnoreCase("char")
                || sqlType.equalsIgnoreCase("nvarchar")
                || sqlType.equalsIgnoreCase("nchar")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("datetime")) {
            return "Date";
        } else if (sqlType.equalsIgnoreCase("image")) {
            return "Blob";
        } else if (sqlType.equalsIgnoreCase("text")) {
            return "Clob";
        }

        return null;
    }

    //
    public static void main( String[] ar ) {
        new GenerateBeanUtil().genEntityTool();
    }

}